import { EventEmitter } from 'stream'
import { WebSocket } from 'ws'
import { ApiMsgEnum, binaryDecode, binaryEncode, IItem, IModel, strdecode, strencode } from '../Common'
import { bufferToArrayBuffer } from '../Utils'
import { MyServer } from './MyServer'

export class Connection extends EventEmitter {
  // socket事件栈
  private msgMap: Map<ApiMsgEnum, Array<IItem>> = new Map()

  constructor(private server: MyServer, private ws: WebSocket) {
    super()

    // 断开连接
    this.ws.on('close', () => {
      this.emit('close')
    })

    // 处理客户端消息
    this.ws.on('message', (buffer: Buffer) => {
      try {
        // const ta = new Uint8Array(buffer)
        // const str = strdecode(ta)
        // const json = JSON.parse(str)

        const json = binaryDecode(bufferToArrayBuffer(buffer))
        const { name, data } = json

        // 处理api请求
        if (this.server.apiMap.has(name)) {
          try {
            const cb = this.server.apiMap.get(name)
            const res = cb.call(null, this, data)
            // 返回给客户端
            this.sendMsg(name, { success: true, res })
          } catch (error) {
            this.sendMsg(name, { success: false, error })
          }
        } else {
          // 执行socekt事件栈
          if (this.msgMap.has(name)) {
            this.msgMap.get(name).forEach(({ cb, ctx }) => {
              cb.call(ctx, this, data)
            })
          }
        }
      } catch (error) {
        console.log(error)
      }
    })
  }

  // 发送信息给服务端
  sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
    const obj = {
      name,
      data,
    }
    const da = binaryEncode(name, data)
    // 传输二进制数据
    // const ta = strencode(JSON.stringify(obj))
    // const buffer = Buffer.from(ta)
    const buffer = Buffer.from(da.buffer)
    this.ws.send(buffer)
  }
  // 事件监听
  listenMsg<T extends keyof IModel['msg']>(name: T, cb: (connection: Connection, args: IModel['msg'][T]) => void, ctx: unknown) {
    if (this.msgMap.has(name)) {
      this.msgMap.get(name).push({ cb, ctx })
    } else {
      this.msgMap.set(name, [{ cb, ctx }])
    }
  }
  // 事件解绑
  unListenMsg<T extends keyof IModel['msg']>(name: T, cb: (connection: Connection, args: IModel['msg'][T]) => void, ctx: unknown) {
    if (this.msgMap.has(name)) {
      const index = this.msgMap.get(name).findIndex(i => cb === i.cb && i.ctx === ctx)
      index > -1 && this.msgMap.get(name).splice(index, 1)
    }
  }
}
